package top.guinguo.index_01.util;

import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.NumericField;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.RAMDirectory;
import org.apache.lucene.util.Version;
import org.junit.Test;

import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by guin_guo on 2016/7/4.
 */
public class IndexUtil {
    private String[] ids = {"1", "2", "3", "4", "5", "6"};
    private String[] emails = {"aa@ggn.org", "bb@ggn.com", "guinguo@sina.com", "five@g.com", "fsdf!@fdf.com", "ggn@ggn.org"};
    private String[] contents = {
            "welcome to visited the space, i like milk...",
            "i like say hello guinguo",
            "i like cyw is a sb and like bbs",
            "we are living in wushan badong like it",
            "i sushehao is 315 like michear",
            "i like play basketball and movie"};
    private int[] attachs = {1, 2, 4, 5, 6, 7};

    private Date[] dates;
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

    private String[] names = {"zhangsan", "lisi", "chengyiz", "chengguanw", "dezp", "guin_guo"};

    private Map<String, Float> score = new HashMap<String, Float>();
    private Directory directory = null;
    private static IndexReader reader = null;
    public IndexUtil() {
        try {
            setDates();
            score.put("ggn.org", 2.0f);
            score.put("g.com", 1.5f);
//            this.directory = FSDirectory.open(new File("E:\\test\\lucene\\index02"));
            directory = new RAMDirectory();
            index();
            reader = IndexReader.open(directory,false);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }

    public IndexSearcher getSearcher() {
        try {
            if (reader == null) {
                reader = IndexReader.open(directory,false);
            } else {
                IndexReader ir = IndexReader.openIfChanged(reader);
                if (ir != null) {
                    reader.close();
                    reader = ir;
                }
                return new IndexSearcher(reader);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    private void setDates() throws ParseException {
        dates = new Date[ids.length];
        for (int i = 0; i < ids.length; i++) {
            dates[i] = sdf.parse("2016-07-0"+(i+1));
        }
    }

    public void undelete() {
        //使用IndexReader进行恢复
        try {
            //恢复时，必须把IndexReader的readOnly设置为false
            IndexReader reader = IndexReader.open(directory,false);
            reader.undeleteAll();
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void merge() {
        IndexWriter writer = null;
        try {
            writer = new IndexWriter(directory, new IndexWriterConfig(Version.LUCENE_35, new StandardAnalyzer(Version.LUCENE_35)));
            writer.forceMerge(4);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                writer.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    public void forceDelete() {
        IndexWriter writer = null;
        try {
            writer = new IndexWriter(directory, new IndexWriterConfig(Version.LUCENE_35, new StandardAnalyzer(Version.LUCENE_35)));
            writer.forceMergeDeletes();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                writer.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @Test
    public void update() {
        IndexWriter writer = null;
        try {
            writer = new IndexWriter(directory, new IndexWriterConfig(Version.LUCENE_35, new StandardAnalyzer(Version.LUCENE_35)));
            //lucene 并没有更新功能，只是下面两个操作一起完成
            Document doc = new Document();
            doc.add(new Field("id", "11", Field.Store.YES,Field.Index.NOT_ANALYZED));
            doc.add(new Field("email",emails[0], Field.Store.YES, Field.Index.NOT_ANALYZED));
            doc.add(new Field("content", contents[0], Field.Store.NO, Field.Index.ANALYZED));
            doc.add(new Field("name",names[0], Field.Store.YES, Field.Index.NOT_ANALYZED));
            writer.updateDocument(new Term("id", "1"),doc);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (writer != null) {
                try {
                    writer.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    @Test
    public void delete() {
        IndexWriter writer = null;
        try {
            writer = new IndexWriter(directory, new IndexWriterConfig(Version.LUCENE_35, new StandardAnalyzer(Version.LUCENE_35)));
            //参数是一个选项，可以是一个Query，也可以是一个Term-精确查找的值
            //回收站，可以恢复
            writer.deleteDocuments(new Term("id", "1"));
            writer.commit();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (writer != null) {
                try {
                    writer.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    @Test
    public void delete2() {
        try {
            reader.deleteDocuments(new Term("id", "1"));
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Test
    public void query() {
        try {
            IndexReader reader = IndexReader.open(directory);
            System.out.println("numdocs:"+reader.numDocs());
            System.out.println("maxdocs:"+reader.maxDoc());
            System.out.println("deldocs:"+reader.numDeletedDocs());
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public void index() {
        IndexWriter writer = null;
        try {
            writer = new IndexWriter(directory, new IndexWriterConfig(Version.LUCENE_35, new StandardAnalyzer(Version.LUCENE_35)));
            writer.deleteAll();
            Document doc = null;
            for (int i = 0; i < ids.length; i++) {
                doc = new Document();
                doc.add(new Field("id", ids[i], Field.Store.YES,Field.Index.NOT_ANALYZED));
                doc.add(new Field("email",emails[i], Field.Store.YES, Field.Index.NOT_ANALYZED));
                doc.add(new Field("content", contents[i], Field.Store.NO, Field.Index.ANALYZED));
                doc.add(new Field("name",names[i], Field.Store.YES, Field.Index.NOT_ANALYZED));
                doc.add(new NumericField("attach",Field.Store.YES,true).setIntValue(attachs[i]));
                doc.add(new NumericField("date", Field.Store.YES, true).setLongValue(dates[i].getTime()));
                //doc.add(new Field("attach", attachs[i], Field.Store.YES, Field.Index.NOT_ANALYZED));
                String et = emails[i].substring(emails[i].lastIndexOf("@") + 1);
                System.out.println(et);
                if (score.containsKey(et)) {
                    doc.setBoost(score.get(et));
                } else {
                    doc.setBoost(0.5f);
                }
                writer.addDocument(doc);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (writer != null) {
                try {
                    writer.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    public void search01() {
        try {
            IndexReader reader = IndexReader.open(directory);
            IndexSearcher searcher = new IndexSearcher(reader);
            TermQuery query = new TermQuery(new Term("content", "like"));
            TopDocs tds = searcher.search(query, 10);
            for (ScoreDoc sd : tds.scoreDocs) {
                Document doc = searcher.doc(sd.doc);
                System.out.println("("+sd.doc+"-"+doc.getBoost()+","+sd.score+")"
                        +doc.get("name")+"["+doc.get("email")+"]-->"+doc.get("id")+","
                        +doc.get("attach")+","+sdf.format(new Date(Long.parseLong(doc.get("date")))));
            }
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void search02() {
        try {
            IndexSearcher searcher = getSearcher();
            TermQuery query = new TermQuery(new Term("content", "like"));
            TopDocs tds = searcher.search(query, 10);
            for (ScoreDoc sd : tds.scoreDocs) {
                Document doc = searcher.doc(sd.doc);
                System.out.println(doc.get("id")+"------->"+
                        "("+sd.doc+"-"+doc.getBoost()+","+sd.score+")"
                        +doc.get("name")+"["+doc.get("email")+"]-->"+doc.get("id")+","
                        +doc.get("attach")+","+sdf.format(new Date(Long.parseLong(doc.get("date")))));
            }
            searcher.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
